using ZLogger.Formatters;

namespace ZLogger;

public enum BackgroundBufferFullMode
{
    /// <summary>
    /// Grow the queue.
    /// </summary>
    Grow,

    /// <summary>
    /// Wait until there's more room in the queue.
    /// </summary>
    Block,

    /// <summary>
    /// Drop the overflowing log entry.
    /// </summary>
    Drop,
}

public class ZLoggerOptions
{
    /// <summary>
    /// `InternalErrorLogger` is a delegate that is called when an exception occurs in the log writing process (such as a serialization error). The default value is `null`, which means errors are ignored.
    /// </summary>
    public Action<Exception>? InternalErrorLogger { get; set; }

    /// <summary>
    /// Enable `ILogger.BeginScope`, default is `false`.
    /// </summary>
    public bool IncludeScopes { get; set; }

    /// <summary>
    /// Gets or sets the time provider for the logger. The Timestamp of LogInfo is generated by TimeProvider's GetUtcNow() and LocalTimeZone when TimeProvider is set. The default value is null, which means use the system standard.
    /// </summary>
    public TimeProvider? TimeProvider { get; set; }

    /// <summary>
    /// Gets or sets behavior when the queue capacity for writing in the background is full
    /// </summary>
    public BackgroundBufferFullMode FullMode { get; set; } = BackgroundBufferFullMode.Grow;

    /// <summary>
    /// Sets the queue capacity for writing in the background; has no meaning if FullMode is Grow.
    /// </summary>
    public int BackgroundBufferCapacity { get; set; } = 10_000;

    /// <summary>
    /// Create an formatter to use in ZLoggerProvider.
    /// </summary>
    public IZLoggerFormatter CreateFormatter() => formatterFactory.Invoke();

    /// <summary>
    /// Fallback of standard logger.Log, message stringify immediately or not. Default is true.
    /// </summary>
    public bool IsFormatLogImmediatelyInStandardLog { get; set; } = true;

    /// <summary>
    /// Capture information about the thread that generated a log entry. Default is false.
    /// </summary>
    public bool CaptureThreadInfo { get; set; } = false;

    Func<IZLoggerFormatter> formatterFactory = DefaultFormatterFactory;

    public ZLoggerOptions UseFormatter(Func<IZLoggerFormatter> formatterFactory)
    {
        this.formatterFactory = formatterFactory;
        return this;
    }

    public ZLoggerOptions UsePlainTextFormatter(Action<PlainTextZLoggerFormatter>? configure = null)
    {
        UseFormatter(() =>
        {
            var formatter = new PlainTextZLoggerFormatter();
            configure?.Invoke(formatter);
            return formatter;
        });
        return this;
    }

    static IZLoggerFormatter DefaultFormatterFactory()
    {
        return new PlainTextZLoggerFormatter();
    }
}
